package edu.ksu.cis.bandera.tool.indus;

import edu.ksu.cis.bandera.tool.Tool;
import edu.ksu.cis.bandera.tool.ToolConfigurationView;
import edu.ksu.cis.bandera.tool.ToolIconView;
import edu.ksu.cis.bandera.tool.indus.configuration.ClassInclude;
import edu.ksu.cis.bandera.tool.indus.configuration.Configuration;
import edu.ksu.cis.bandera.tool.indus.configuration.Includes;
import edu.ksu.cis.bandera.tool.indus.configuration.MethodInclude;
import edu.ksu.cis.bandera.tool.indus.configuration.Param;
import edu.ksu.cis.bandera.tool.indus.configuration.Params;
import edu.ksu.cis.bandera.util.BaseObservable;
import edu.ksu.cis.indus.slicer.SliceCriteriaFactory;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import soot.Scene;
import soot.SootClass;
import soot.SootMethod;

public final class SlicerCriteriaFactoryTool extends BaseObservable
  implements Tool
{
  public static final String DEFAULT_CONFIGURATION_STRING = "<configuration idref=\"default\"/>";
  private String config;
  private Scene scene;
  private Collection sliceCriteriaCollection;
  private Set classSet;
  private Set methodSet;
  private static IndusConfigurationLibrary configurationLibrary;
  private static List INPUT_PARAMETER_LIST;
  public static final String SCENE_INPUT_KEY = "scene";
  private static List OUTPUT_PARAMETER_LIST;
  public static final String SLICE_CRITERION_KEY = "sliceCriterion";

  private static void initConfigurationLibrary()
  {
    try
    {
      configurationLibrary = new IndusConfigurationLibrary();
    } catch (Exception e) {
      throw new RuntimeException("A fatal exception was thrown while loading the default configuration library.", e);
    }
  }

  public SlicerCriteriaFactoryTool()
  {
    this.sliceCriteriaCollection = new HashSet();
    this.classSet = new HashSet();
    this.methodSet = new HashSet();
  }

  private static void initInputParameterList()
  {
    INPUT_PARAMETER_LIST = new ArrayList(1);
    INPUT_PARAMETER_LIST.add("scene");
  }

  private static void initOutputParameterList()
  {
    OUTPUT_PARAMETER_LIST = new ArrayList(1);
    OUTPUT_PARAMETER_LIST.add("sliceCriterion");
  }

  public String getConfiguration()
  {
    return this.config;
  }

  public List getInputParameterList()
  {
    return INPUT_PARAMETER_LIST;
  }

  public Map getOutputMap()
  {
    Map outputMap = new HashMap(1);
    outputMap.put("sliceCriterion", this.sliceCriteriaCollection);
    return outputMap;
  }

  public List getOutputParameterList()
  {
    return OUTPUT_PARAMETER_LIST;
  }

  public ToolConfigurationView getToolConfigurationView()
  {
    return null;
  }

  public ToolIconView getToolIconView()
  {
    return null;
  }

  public void quit()
  {
  }

  public void run()
    throws IllegalStateException
  {
    if (this.scene == null) {
      throw new IllegalStateException("Cannot run with a null Scene.");
    }

    SliceCriteriaFactory scf = SliceCriteriaFactory.getFactory();

    Iterator csi = this.classSet.iterator();
    while (csi.hasNext()) {
      String className = (String)csi.next();
      if (this.scene.containsClass(className)) {
        SootClass sootClass = this.scene.getSootClass(className);
        List sootMethodList = sootClass.getMethods();
        if (sootMethodList != null) {
          Iterator smli = sootMethodList.iterator();
          while (smli.hasNext()) {
            SootMethod sootMethod = (SootMethod)smli.next();
            Collection c = scf.getCriteria(sootMethod);
            this.sliceCriteriaCollection.addAll(c);
          }
        }
      }
    }

    Iterator msi = this.methodSet.iterator();
    while (msi.hasNext()) {
      String methodName = (String)msi.next();
      if (this.scene.containsMethod(methodName)) {
        SootMethod sootMethod = this.scene.getMethod(methodName);
        Collection c = scf.getCriteria(sootMethod);
        this.sliceCriteriaCollection.addAll(c);
      }
    }
  }

  public void setConfiguration(String newConfig)
    throws Exception
  {
    this.config = newConfig;

    this.classSet.clear();
    this.methodSet.clear();

    StringReader configStringReader = null;
    if ((this.config == null) || (this.config.length() <= 0))
      configStringReader = new StringReader("<configuration idref=\"default\"/>");
    else {
      configStringReader = new StringReader(this.config);
    }

    Configuration configuration = null;
    try {
      configuration = Configuration.unmarshal(configStringReader);
    } catch (Exception e) {
      throw new Exception("An exception occurred while parsing the configuration String.", e);
    }

    if (configuration != null) {
      String idref = configuration.getIdref();
      if ((idref != null) && (idref.length() > 0)) {
        Configuration c = configurationLibrary.getConfiguration(idref);
        if (c != null) {
          configuration = c;
        }
      }
      Includes includes = configuration.getIncludes();
      if (includes != null) {
        String includesIDREF = includes.getIdref();
        if ((includesIDREF != null) && (includesIDREF.length() > 0)) {
          Includes i = configurationLibrary.getIncludes(includesIDREF);
          if (i != null) {
            includes = i;
          }
        }
        for (int i = 0; i < includes.getClassIncludeCount(); ++i) {
          ClassInclude classInclude = includes.getClassInclude(i);
          String classIncludeIDREF = classInclude.getIdref();
          if ((classIncludeIDREF != null) && (classIncludeIDREF.length() > 0)) {
            ClassInclude ci = configurationLibrary.getClassInclude(classIncludeIDREF);
            if (ci != null) {
              classInclude = ci;
            }
          }
          String className = NameConstructor.constructClassName(classInclude.getName());
          this.classSet.add(className);
        }

        for (int i = 0; i < includes.getMethodIncludeCount(); ++i) {
          MethodInclude methodInclude = includes.getMethodInclude(i);
          String methodIncludeIDREF = methodInclude.getIdref();
          if ((methodIncludeIDREF != null) && (methodIncludeIDREF.length() > 0)) {
            MethodInclude mi = configurationLibrary.getMethodInclude(methodIncludeIDREF);
            if (mi != null) {
              methodInclude = mi;
            }
          }
          List paramTypeList = new ArrayList();
          Params params = methodInclude.getParams();
          if (params != null) {
            for (int pi = 0; pi < params.getParamCount(); ++pi) {
              Param p = params.getParam(pi);
              paramTypeList.add(p.getType());
            }
          }
          String className = methodInclude.getClassName();
          String methodName = methodInclude.getName();
          String returnType = methodInclude.getReturnType();
          String sootMethodSignature = NameConstructor.constructMethodName(className, methodName, paramTypeList, returnType);
          this.methodSet.add(sootMethodSignature);
        }
      }
    }
  }

  public void setInputMap(Map inputMap)
    throws IllegalArgumentException
  {
    if (inputMap == null) {
      throw new IllegalArgumentException("Cannot set a null input Map.");
    }

    if (inputMap.size() < 1) {
      throw new IllegalArgumentException("The input Map must contain at least 1 key/value pair.");
    }

    Object sceneObject = inputMap.get("scene");
    if (sceneObject == null) {
      throw new IllegalArgumentException("Cannot use a null Scene.");
    }
    if (!(sceneObject instanceof Scene)) {
      throw new IllegalArgumentException("Cannot use a Scene that is not of type soot.Scene.");
    }

    this.scene = ((Scene)sceneObject);
  }

  static
  {
    initInputParameterList();
    initOutputParameterList();
    initConfigurationLibrary();
  }
}

/* Location:           D:\tool\banderaCLI-1.0a4\lib\bandera\bandera.jar
 * Qualified Name:     edu.ksu.cis.bandera.tool.indus.SlicerCriteriaFactoryTool
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.5.3
 */